# coding= utf-8

import requests
import json
import sys
import codecs
import warnings
import pymongo
import time

sys.stdout = codecs.getwriter('utf-8')(sys.stdout.detach())
warnings.filterwarnings("ignore")


class Low:
    def __init__(self):
        self.lr = {}
        self.api_prefix = 'https://api.keepa.com/product'
        self.api_key = 'r4mmbkscb3hgclav1f45dpg61tf0gga07eb91kbfqf253dl99d5jdvfkil1scvec'  # 付费token
        self.asset_url = 'https://m.media-amazon.com/images/I/'
        self.token_url = 'https://api.keepa.com/token'
        self.asin_list = []
        self.no_sale = []
        self.domain = ''
        self.country_desc = ''
        self.month = sys.argv[1]
        # self.month = '2024-08'
        self.asin_num = {}
        self.asin_counts = {}
        self.sku_count = {}
        self.group_name = {}

        # 连接MongoDB
        self.myclient = pymongo.MongoClient("mongodb://localhost:27017/")
        mydb = self.myclient["xp_analyse"]
        self.my_asin = mydb["wt_asin"]
        self.my_product = mydb["wt_order_product"]
        self.my_task = mydb["wt_task"]
        self.low_product = mydb["wt_product"]
        self.low_order = mydb["wt_low_order"]
        self.task_country = mydb["wt_task_country"]

    def get_asin(self, domain, asin, asin_group):
        # 判断令牌剩余数量
        params = {
            'key': self.api_key
        }
        response = requests.get(url=self.token_url, params=params)
        res = json.loads(response.text)
        token_left = int(res['tokensLeft'])

        # 令牌不足退出
        if token_left < 300:
            print('Token不足，等待60s， 剩余 ' + str(token_left))
            time.sleep(60)
            self.get_asin(domain, asin, asin_group)
        else:
            print('Token剩余 ' + str(token_left))

            # 请求asin信息
            country = translate_domain(domain)

            # 法德意西为欧洲，英国、美国、日本、加拿大
            if country in ['fr', 'de', 'it', 'es']:
                self.country_desc = '欧洲四国'
            elif country == 'uk':
                self.country_desc = '英国'
            elif country == 'us':
                self.country_desc = '美国'
            elif country == 'jp':
                self.country_desc = '日本'
            elif country == 'ca':
                self.country_desc = '加拿大'

            url = self.api_prefix
            params = {
                'key': self.api_key,
                'domain': int(domain),
                'asin': asin,
                'rating': 1,
                'stats': 180,
                'update': 6,
                'history': 0
            }
            response = requests.get(url=url, params=params)

            # 判断状态码
            status_code = response.status_code
            if not int(status_code) == 200:
                print('状态码：' + str(status_code) + '请求失败，等待下次重试！')
                time.sleep(3)
                self.get_asin(domain, asin, asin_group)
            else:
                no_order_asin = []
                res = json.loads(response.text)

                # 判断请求是否成功
                if "error" in res:
                    print(res['error']['message'])

                if "products" in res:
                    for i in res['products']:
                        category_list = []

                        sales_rank_current = int(i['stats']['current'][3])
                        reviews_review_count = int(i['stats']['current'][17])

                        if 'imagesCSV' in i and not i['imagesCSV'] == None:
                            image = self.asset_url + i['imagesCSV'].split(',')[0]
                        else:
                            image = ''
                        if 'categoryTree' in i:
                            category_tree = i['categoryTree']
                        else:
                            category_tree = ''
                        if category_tree:
                            for tree in category_tree:
                                category_list.append(tree['name'])

                        # 判断没有价格，则为不在售
                        buy_box_current = float(i['stats']['current'][1] / 100)
                        if buy_box_current < 0:
                            status = '不在售'
                        else:
                            status = '在售'

                        # 判断是否店铺有此产品
                        title = i.get('title', '')
                        if not title:
                            for g in asin_group[i.get('asin')]:
                                no_sale_asin = {
                                    'asin': i.get('asin'),
                                    'group_name': g,
                                    'country': country,
                                }

                                # 添加到店铺无列表中，等待结束前请求ceping-system标记店铺无
                                self.no_sale.append(no_sale_asin)

                        for g_name in asin_group[i.get('asin')]:
                            value = dict([
                                ['domain_id', int(domain)],
                                ['country', country],
                                ['country_desc', self.country_desc],
                                ['month', self.month],
                                ['asin', i.get('asin', '')],
                                ['group_name', g_name],
                                ['image', image],
                                ['title', title],
                                ['buy_box_current', buy_box_current],
                                ['sales_rank_current', sales_rank_current],
                                ['reviews_rating', float(i['stats']['current'][16] / 10)],
                                ['reviews_review_count', reviews_review_count],
                                ['categories_tree', ' > '.join(category_list)],
                                ['status', status],
                                ['order_num', 0],
                                ['create_time', int(time.time())],
                                ['update_time', int(time.time())],
                            ])
                            no_order_asin.append(value)

                    # 插入总产品表
                    if len(no_order_asin) > 0:
                        result = self.low_product.insert_many(no_order_asin)

                        # 检查插入操作是否成功
                        if result.acknowledged:
                            print('插入订单表成功，共计' + str(len(no_order_asin)) + '条！')
                        else:
                            print('插入失败，等待下次重新获取！')
                    else:
                        print('暂无低订单asin数据！')
                else:
                    print('返回结果无产品！')

                # 标记已获取产品信息的asin
                asin_arr = asin.split(',')
                if self.my_asin.update_many({'month': self.month, 'asin': {'$in': asin_arr}, "country": country},
                                            {'$set': {'check_sale_state': True}}):
                    print('标记已获取信息asin，共计' + str(len(asin_arr)) + '条！')
                else:
                    print('标记失败，等待下次标记！')

    def get_wt_asin(self):
        task = self.my_task.find_one({"month": self.month})

        # 创建索引
        indexlist = self.low_product.index_information()
        if not indexlist:
            self.low_product.create_index("asin")
            self.low_product.create_index("domain_id")
            self.low_product.create_index("country")
            self.low_product.create_index("group_name")

        try:
            if int(task['low_orders_completed']['wt_low_order']['value']) == 0:
                # 更新状态为处理中
                self.my_task.update_one({"month": self.month}, {"$set": {"low_orders_completed.wt_low_order.loading": True}})


                for i in ['jp', 'us', 'uk', 'es', 'it', 'fr', 'ca', 'de']:
                    # 验证该国家是否已跑过
                    task_country = self.task_country.find_one({'month': self.month, 'country': i, 'status': 1})
                    if task_country:
                        print('国家' + i + '已跑，跳过')
                        continue

                    # 获取各个国家asin在售信息
                    self.no_sale = []  # 循环新国家时，清空历史国家的不在售记录
                    self.get_country_asin(i)
                    print('国家' + i + '更新完毕！')

                    # 更新完毕添加国家完成记录
                    record = {
                        'month': self.month,
                        'country': i,
                        'status': 1,
                    }
                    self.task_country.insert(record)

                    # 请求测评system，更新不在售的asin数据
                    # if len(self.no_sale):
                    #     self.post_to_cep()

                # 根据wt_product表中数据，规整到wt_low_order表中
                # self.comb_data_to_low()

                # 更新状态为已完成
                self.my_task.update_one({"month": self.month}, {"$set": {"low_orders_completed.wt_low_order.value": 1, "low_orders_completed.wt_low_order.loading": False}})
            else:
                print('该月份数据已生成！')
            print('更新完毕')
            self.myclient.close()
            exit()
        except Exception as e:
            print(e)
            self.myclient.close()
            exit()

    def get_country_asin(self, country):
        # url = "http://local-sys.com/common/analyse/get_company_asin"
        url = "https://wangting.wszzl.cn/common/analyse/get_company_asin"
        params = {'country': country.upper()}

        # 发起GET请求，并传递参数
        response = requests.get(url, params=params)

        # 检查请求是否成功
        if response.status_code == 200:
            data = response.json()
            print(country)

            # 创建索引
            asinIndexlist = self.my_asin.index_information()
            if not asinIndexlist:
                self.my_asin.create_index("asin")
                self.my_asin.create_index("country")
                self.my_asin.create_index("group_name")
                self.my_asin.create_index("month")

            # 插入wt_asin表中
            asin_total = []
            if len(data['data']):
                for i in data['data']:
                    info = i.split('#$%|')

                    value = dict([
                        ['asin', info[0]],
                        ['month', self.month],
                        ['country', country],
                        ['domain_id', translate_locale(country)],
                        ['group_name', info[1]],
                        ['create_time', int(time.time())],
                        ['update_time', int(time.time())],
                    ])
                    asin_total.append(value)
                if len(asin_total) > 0:
                    result = self.my_asin.insert_many(asin_total)

                    # 检查插入操作是否成功
                    if result.acknowledged:
                        print('获取asin记录成功，共计' + str(len(asin_total)) + '条！')

                        # 获取asin信息
                        self.asin_order_info(country)
                    else:
                        print('插入失败，等待下次重新获取！')
                else:
                    print('暂无asin数据！')
            else:
                print('国家' + country + '，暂无asin数据！')
        else:
            # 如果请求不成功，打印错误信息
            print("请求失败，状态码：", response.status_code)
            print(response.text)  # 可以打印出服务器返回的错误信息

    # 获取asin订单量信息
    def asin_order_info(self, country):
        # 等待keepa获取在售信息asin列表，每凑满100请求一次，并清空
        asin_wait = []
        asin_group = {}

        asins = self.my_asin.find({'check_sale_state': {'$exists': False}, 'month': self.month, 'country': country,
                                   'asin': {"$ne": None, '$exists': True}})

        for i in asins:
            product_info = self.my_product.find_one(
                {'month': self.month, 'locale': country, 'asin': i.get('asin'), 'group_name': i.get('group_name')})

            if product_info:
                print('------有订单信息')
                state = self.my_asin.update_many({'month': self.month, 'asin': i.get('asin'), "country": country},
                                                 {'$set': {'check_sale_state': True}})
                print('更新asin' + i.get('asin') + '已获取状态：' + str(state.acknowledged))

                # 在订单产品表中有，更新低订单分析表中asin单量
                order_num = product_info.get('order_num')
                if int(order_num) < 10:
                    value = dict([
                        ['domain_id', translate_locale(country)],
                        ['country', country],
                        ['country_desc', self.country_desc],
                        ['month', self.month],
                        ['asin', product_info.get('asin', '')],
                        ['group_name', product_info.get('group_name')],
                        ['image', product_info.get('image')],
                        ['title', product_info.get('title', '')],
                        ['buy_box_current', product_info.get('buy_box_current')],
                        ['sales_rank_current', product_info.get('sales_rank_current')],
                        ['reviews_rating', product_info.get('reviews_rating')],
                        ['reviews_review_count', product_info.get('reviews_review_count')],
                        ['categories_tree', product_info.get('categories_tree')],
                        ['status', '在售'],
                        ['order_num', product_info.get('order_num')],
                        ['create_time', int(time.time())],
                        ['update_time', int(time.time())],
                    ])

                    # 插入总产品表
                    self.low_product.insert(value)
                    print('asin：' + product_info.get('asin') + '，订单量少于10单，为：' + str(order_num))
                else:
                    print('asin：' + product_info.get('asin') + '，订单量多于10单，为：' + str(order_num))
            else:
                if i.get('asin') not in asin_wait:
                    asin_wait.append(i.get('asin'))

                # 如果asin不在字典中，创建一个新列表
                if i.get('asin') not in asin_group:
                    asin_group[i.get('asin')] = []

                # 如果group_name不在列表中，则添加
                if i.get('group_name') not in asin_group[i.get('asin')]:
                    asin_group[i.get('asin')].append(i.get('group_name'))

            # 满100 请求keepa
            if len(asin_wait) >= 100:
                print('满100asin，请求keepa 获取在售信息。')
                domain = translate_locale(country)
                asin_str = ','.join(asin_wait)
                self.get_asin(domain, asin_str, asin_group)

                asin_wait = []
                asin_group = {}
                print('清空待请求asin列表')

        if len(asin_wait):
            print('最后还有asin' + str(len(asin_wait)) + '条，继续请求')
            domain = translate_locale(country)
            asin_str = ','.join(asin_wait)
            self.get_asin(domain, asin_str, asin_group)

    # 将不在售asin发送到测评系统
    def post_to_cep(self):
        # url = "http://local-sys.com/common/analyse/insert_no_sale_asin"
        url = "https://wangting.wszzl.cn/common/analyse/insert_no_sale_asin"
        json_data = {
            'asins': json.dumps(self.no_sale),
        }

        response = requests.post(url, data=json_data)

        # 检查请求是否成功
        if response.status_code == 200:
            data = response.json()
            print(data)
        else:
            # 如果请求不成功，打印错误信息
            print("请求失败，状态码：", response.status_code)
            print(response.text)  # 可以打印出服务器返回的错误信息

    # 整合数据
    def comb_data_to_low(self):
        # 创建索引
        indexlist = self.low_order.index_information()
        if not indexlist:
            self.low_order.create_index("asin")
            self.low_order.create_index("country_desc")
            self.low_order.create_index("group_name")
            self.low_order.create_index("month")
            self.low_order.create_index("status")

        low_insert = []
        pipeline = [
            {'$match': {'month': self.month}},
            {
                '$group': {
                    '_id': {
                        'asin': '$asin',
                        'month': '$month',
                        'group_name': '$group_name',
                        'country_desc': '$country_desc'
                    },
                    'title': {'$first': '$title'},
                    'image': {'$first': '$image'},
                    'categories_tree': {'$first': '$categories_tree'},
                    'order_num': {
                        '$sum': '$order_num'
                    },
                    'statuses': {'$addToSet': '$status'},
                    'unique_title': {'$addToSet': '$title'},
                },
            },
            {
                '$project': {
                    '_id': 1,
                    'order_num': 1,
                    'title': 1,
                    'image': 1,
                    'categories_tree': 1,
                    'unique_title': 1,
                    'status': {
                        '$cond': [
                            {'$in': ['不在售', '$statuses']},
                            '不在售',
                            '在售'
                        ]
                    }
                }
            }
        ]
        for item in self.low_product.aggregate(pipeline, allowDiskUse=True):
            order_num = item.get('order_num')
            if order_num <= 10:
                # 自动标记不在售和店铺无
                limit_type = ''
                limit_reason = ''

                status = item.get('status')
                if status == '不在售':
                    limit_type = 0
                    limit_reason = '系统标记不在售'

                unique_title = item.get('unique_title', [None])
                if all_none(unique_title):
                    limit_type = 1
                    limit_reason = '系统标记店铺无'

                value = dict([
                    ['asin', item['_id']['asin']],
                    ['month', item['_id']['month']],
                    ['group_name', item['_id']['group_name']],
                    ['country_desc', item['_id']['country_desc']],
                    ['title', item.get('title', '')],
                    ['image', item.get('image', '')],
                    ['categories_tree', item.get('categories_tree', '')],
                    ['order_num', order_num],
                    ['status', status],
                    ['limit_type', limit_type],
                    ['limit_reason', limit_reason],
                    ['is_human', ''],
                    ['create_time', int(time.time())],
                    ['update_time', int(time.time())],
                ])
                low_insert.append(value)

        # 插入低订单产品表
        if len(low_insert) > 0:
            result = self.low_order.insert_many(low_insert)

            # 检查插入操作是否成功
            if result.acknowledged:
                print('插入低订单表成功，共计' + str(len(low_insert)) + '条！')
            else:
                print('插入低订单失败！')
        else:
            print('暂无低订单数据！')


def translate_domain(domain):
    dis = {1: 'us', 2: 'uk', 3: 'de', 4: 'fr', 5: 'jp', 6: 'ca', 8: 'it', 9: 'es', 10: 'in', 11: 'mx'}
    return dis.get(domain)


def translate_locale(domain):
    dis = {'us': 1, 'uk': 2, 'de': 3, 'fr': 4, 'jp': 5, 'ca': 6, 'it': 8, 'es': 9, 'in': 10, 'mx': 11}
    return dis.get(domain)


def translate_time(keepa_time):
    return (keepa_time + 21564000) * 60


def all_none(lst):
    return all(element is None for element in lst)


low = Low()
low.get_wt_asin()
